import shutil
import os
import subprocess
import time
from typing import Optional, Tuple

class HotUpdater:
    """热更新操作管理器"""
    
    # 常量定义
    UNITY_PATH = r"D:\Unity Hub\Hub_Install\2023.2.20f1c1\Editor\Unity.exe"
    PROJECT_PATH = r"D:\Project\HotFix_Test\HybridCLR_Project"
    SOURCE_DLL = os.path.join(PROJECT_PATH, "HybridCLRData/HotUpdateDlls/StandaloneWindows64/HotUpdate.dll")
    TARGET_DIR = os.path.join(PROJECT_PATH, "Build/HybridCLR_ProJect_Data/StreamingAssets")
    EXE_PATH = os.path.join(PROJECT_PATH, "Build/HybridCLR_Project.exe")

    @classmethod
    def build_hot_dll(cls) -> bool:
        """编译HybridCLR DLL"""
        command = [
            cls.UNITY_PATH,
            "-batchmode",
            "-nographics",
            "-projectPath", cls.PROJECT_PATH,
            "-executeMethod", "AutoCompileHybridCLR.AutoCompile",
            "-logFile", os.path.join(cls.PROJECT_PATH, "compile_log.txt"),
            "-quit"
        ]
        
        print("开始编译HybridCLR DLL...")
        try:
            result = subprocess.run(
                command,
                capture_output=True,
                text=True,
                check=True
            )
            print("HybridCLR DLL编译成功！")
            return True
        except subprocess.CalledProcessError as e:
            print(f"编译失败，错误码: {e.returncode}")
            print(f"错误输出:\n{e.stderr}")
            cls._open_explorer(cls.PROJECT_PATH)
            return False

    @classmethod
    def move_hot_dll(cls) -> bool:
        """移动DLL文件"""
        try:
            os.makedirs(cls.TARGET_DIR, exist_ok=True)
            target_path = os.path.join(cls.TARGET_DIR, "HotUpdate.dll.bytes")
            
            if not os.path.exists(cls.SOURCE_DLL):
                print(f"源文件 {cls.SOURCE_DLL} 不存在！")
                return False
                
            shutil.copy(cls.SOURCE_DLL, target_path)
            print(f"文件已复制到: {target_path}")
            cls._open_explorer(cls.TARGET_DIR)
            return True
        except Exception as e:
            print(f"文件操作失败: {str(e)}")
            return False

    @classmethod
    def run_game(cls) -> bool:
        """运行游戏"""
        try:
            if not os.path.exists(cls.EXE_PATH):
                print(f"错误：游戏执行文件 {cls.EXE_PATH} 不存在！")
                return False
                
            subprocess.Popen(cls.EXE_PATH)
            print(f"成功启动游戏: {cls.EXE_PATH}")
            return True
        except Exception as e:
            print(f"启动游戏失败: {str(e)}")
            return False

    @staticmethod
    def kill_unity_process() -> bool:
        """终止Unity进程"""
        try:
            result = subprocess.run(
                ['taskkill', '/F', '/IM', 'Unity.exe'],
                capture_output=True,
                text=True
            )
            if result.returncode == 0:
                print("已关闭所有Unity进程")
                return True
            print("未找到运行的Unity进程")
            return False
        except Exception as e:
            print(f"关闭进程时出错: {str(e)}")
            return False

    @staticmethod
    def _open_explorer(path: str) -> None:
        """打开资源管理器"""
        try:
            os.startfile(path)
        except Exception as e:
            print(f"无法打开资源管理器: {str(e)}")

    @classmethod
    def execute_pipeline(cls) -> None:
        """执行完整流程"""
        print("开始热更新流程".center(50, '='))
        
        # 处理Unity进程
        if cls._get_user_confirm("是否关闭Unity进程？"):
            cls.kill_unity_process()
            print("等待进程清理...")
            time.sleep(2)

        # 执行编译
        if cls.build_hot_dll():
            print("-" * 50)
            if cls.move_hot_dll():
                print("-" * 50)
                cls.run_game()

    @staticmethod
    def _get_user_confirm(prompt: str) -> bool:
        """获取用户确认"""
        while True:
            choice = input(f"{prompt} (y/n): ").lower()
            if choice in {'y', 'yes'}:
                return True
            if choice in {'n', 'no'}:
                return False
            print("请输入 y/yes 或 n/no")

if __name__ == "__main__":
    HotUpdater.execute_pipeline()
    input("按回车键退出...")